package org.andengine.entity.shape;

import org.andengine.engine.camera.Camera;
import org.andengine.entity.primitive.Line;
import org.andengine.opengl.shader.ShaderProgram;
import org.andengine.util.algorithm.collision.RectangularShapeCollisionChecker;

/**
 * (c) 2010 Nicolas Gramlich
 * (c) 2011 Zynga Inc.
 *
 * @author Nicolas Gramlich
 * @since 11:37:50 - 04.04.2010
 */
public abstract class RectangularShape extends Shape implements IAreaShape {
    // ===========================================================
    // Constants
    // ===========================================================

    // ===========================================================
    // Fields
    // ===========================================================

    protected float mWidth;
    protected float mHeight;

    // ===========================================================
    // Constructors
    // ===========================================================

    public RectangularShape(final float pX, final float pY, final float pWidth, final float pHeight, final ShaderProgram pShaderProgram) {
        super(pX, pY, pShaderProgram);

        this.mWidth = pWidth;
        this.mHeight = pHeight;

        this.resetRotationCenter();
        this.resetScaleCenter();
        this.resetSkewCenter();
    }

    // ===========================================================
    // Getter & Setter
    // ===========================================================

    @Override
    public float getWidth() {
        return this.mWidth;
    }

    @Override
    public float getHeight() {
        return this.mHeight;
    }

    @Override
    public void setWidth(final float pWidth) {
        this.mWidth = pWidth;
        this.onUpdateVertices();
    }

    @Override
    public void setHeight(final float pHeight) {
        this.mHeight = pHeight;
        this.onUpdateVertices();
    }

    @Override
    public void setSize(final float pWidth, final float pHeight) {
        this.mWidth = pWidth;
        this.mHeight = pHeight;
        this.onUpdateVertices();
    }

    @Override
    public float getWidthScaled() {
        return this.getWidth() * this.mScaleX;
    }

    @Override
    public float getHeightScaled() {
        return this.getHeight() * this.mScaleY;
    }

    // ===========================================================
    // Methods for/from SuperClass/Interfaces
    // ===========================================================

    @Override
    public boolean isCulled(final Camera pCamera) {
        return !RectangularShapeCollisionChecker.isVisible(pCamera, this);
    }

    @Override
    public void reset() {
        super.reset();

        this.resetRotationCenter();
        this.resetSkewCenter();
        this.resetScaleCenter();
    }

    @Override
    public boolean contains(final float pX, final float pY) {
        return RectangularShapeCollisionChecker.checkContains(this, pX, pY);
    }

    @Override
    public float[] getSceneCenterCoordinates() {
        return this.convertLocalToSceneCoordinates(this.mWidth * 0.5f, this.mHeight * 0.5f);
    }

    @Override
    public float[] getSceneCenterCoordinates(final float[] pReuse) {
        return this.convertLocalToSceneCoordinates(this.mWidth * 0.5f, this.mHeight * 0.5f, pReuse);
    }

    @Override
    public boolean collidesWith(final IShape pOtherShape) {
        if (pOtherShape instanceof RectangularShape) {
            return RectangularShapeCollisionChecker.checkCollision(this, (RectangularShape) pOtherShape);
        } else if (pOtherShape instanceof Line) {
            return RectangularShapeCollisionChecker.checkCollision(this, (Line) pOtherShape);
        } else {
            return false;
        }
    }

    // ===========================================================
    // Methods
    // ===========================================================

    public void resetRotationCenter() {
        this.mRotationCenterX = this.mWidth * 0.5f;
        this.mRotationCenterY = this.mHeight * 0.5f;
    }

    public void resetScaleCenter() {
        this.mScaleCenterX = this.mWidth * 0.5f;
        this.mScaleCenterY = this.mHeight * 0.5f;
    }

    public void resetSkewCenter() {
        this.mSkewCenterX = this.mWidth * 0.5f;
        this.mSkewCenterY = this.mHeight * 0.5f;
    }

    // ===========================================================
    // Inner and Anonymous Classes
    // ===========================================================
}
